概要
任意の組織で使われているアプリケーションをよく見てみると、ほとんどのアプリケーションは場当たり的に統合されている。時間の経過とともにアプリケーションの種類が増えるにつれて、システムとアプリケーションの相互接続は、まるでさんご礁のように見えてくる。さんご礁は、内側が固くて丈夫で、外側に生命体が集まる。しっかり結合された統合ポイントをいじり回していると、副作用が連続的に発生する可能性があり、だれも問題の根本原因をあえて修正しようとしなくなる。一般的には、高度に結合されたシステムとアプリケーションで構成されたさんご礁の上に、単に新しい層を付加することで問題を修正しようとする。
このような落とし穴に陥らないようにするには、考え方を変える必要がある。IT システムは進化するという考え方を受け入れ、進化を続ける IT システムの組織内での利用方法も変化すると考える必要がある。これを実現するには、自社の IT 設備の進化を補完するような統合戦略を採択するしかない。
今回の一連の記事では、よく知られている統合パターンとオープンソース統合プラットフォームの Mule を使って、これを実現する方法を紹介する。
ストーリー
Kjetil と Rune は IT 担当者であることに嫌気がさし、仕事をやめることにした。そして、ノルウェイの山岳リゾート地トリシルのスキー場の近くに職を求めて転々とする回るスキー狂になる。
ふたりは、どうにかこうにか生計を立てることができ、スキー熱狂者に有益なスキー情報を提供するオンラインアプリケーション PowderAlert を作成することにした。
PowderAlert #1
最初のバージョンの PowderAlert はきわめてシンプルなものである。このアプリケーションの主目的は、E メールを利用して要求に応じてスキー情報を提供するという Kjetil と Rune のビジネスアイデアの主要原則をテストすることである。実際にどのような方法でお金を得るかについては、まだ解決策が見つかっていない。
以下の図 1(source)に、アプリケーションの流れを示す。
図 1: PowderAlert の利用方法と主要コンポーネント
- エンドユーザーが、キーワードとして「powder」ということばを記載した E メールを特定の E メールアドレスに送信する。
- PowderAlert アプリケーションが一定間隔で E メールアカウントに対してポーリングを行い、受信箱のメールの POP を調べ、ユーザのメールアドレスを保存する。
- PowderAlert が公共のサイトから有益なスキー情報を収集する。収集したスキー情報が E メールで PowderAlert アプリケーションに送信される。
- PowderAlert がスキー情報を記載した E メールを一定間隔で集める。
- 情報を記載した E メールがユーザに送信される。
- ユーザが情報を読む。
現在の実施状況
トリシルの有名なアフタースキーの場所 Laaven で長時間にわたる夜のパーティを行なったあと、ふたりは簡単で粗野な PowderAlert アプリケーションを作成することにした。主に降雪情報を収集することに注力し、その情報を配信することについてはあまり考えていなかったため、情報を自動的に配信する方法を考え出す必要があった。ふたりは、インターネットでこの種の情報を提供しているサイトを探した結果、Skiinfo と呼ばれるノルウェーのサイトにたどり着いた。Skiinfo では、パウダーアラームの E メールと SMS メッセージだけでなく、日々の積雪情報も提供している。
Kjetil と Rune は、Spring のフレームワークを利用した実際のシンプルなアプリケーションの作成を開始した。Spring は、JavaMailSender と SimpleMailMessage によって、E メールの送信を見事にサポートしている。また、ユーザを登録するための軽いデータベースも必要だったので、まずは Hypersonic SQL を使ってみることにした。SQL は明らかに彼らの好きな言語ではないため、Hibernate と Annotations を取りれる。2006 年に開発された JAVA プログラムの中で、Java 5 の新しい言語機能を使わずに開発されたものはないと言われている。
もちろん、彼らは Maven 2 の世界に飛び込みたかったので、ベストプラクティスと標準規格に従ってプロジェクトを開始することにした。そのような慣習の 1 つとして、当然ながらテスト駆動開発がある。メールサーバがアプリケーションのこのような中央ポイントにある場合、キャンピングカー内でテスト駆動開発をオフラインで実行することは難しい。救世主となったのは Dumbster である。Dumbster (サイト・英語)は、ユニットのテストを目的として作成された非常にシンプルな偽の SMTP サーバである。
アプリケーションは、コアと Web といった 2 つのモジュールで構成されている。コアの構成要素はドメインモデル、そしてメールサーバに対してポーリングを行なったり、データベースを検索してスキー熱狂者に E メールを送信したりするすべてのサービスである。Web モジュールの主な構成要素は、ポーリングとユーザインターフェイスを処理するブートストラッピングサーブレットである。
以下の図に、PowderAlert ver.1 の主な機能を示す。
図 2: PowderAlert #1 の主な用途
図 2 に示したように、関与しているアクターは、PowderAlert に加入しているユーザ、メールサーバ、そしてPowderAlert にスキー情報を提供するスキー情報サイトである。
簡単に言うと、PowderAlert には以下の 4 つの用途がある。
- パウダーアラートユーザの登録
- パウダーアラートの送信
- その場所にいるパウダーアラートユーザの取得
- パウダーアラームの受信
パウダーアラートの用途
上述のパウダーアラートの用途は、システムの実際の仕組みについて、いくらかの詳細を示すものである。私たちは、システムシーケンス図のようなものを使って、これを記録した。実際の UML 表記は完全に正しいものではないが、Craig Larman 氏(サイト・英語)にお願いしたい。貴方のすばらしい書籍『UML とパターンの適用』(source)に記載されたガイドラインに従わなかったことに対して、20 回以上のむち打ちの刑を与えないでいただきたい。
図 3: 登録手順
上記の図 3 (source)は、登録プロセスを詳細に示すシーケンス図である。特に刺激的なことはないが、ユーザは関心があるスキー場に登録できるという点には言及しておくべきだろう。この情報はあとで、スキー情報のサイトからパウダーアラームを受信した際に使用される。
パウダーアラームの受信の詳細を以下の図 4(source)に示す。
図 4: パウダーアラートの送信
パウダーアラートシステムは、地域ごとに外部システムから降雪情報を受信する。図 4 (source)に示したとおり、任意の場所の降雪情報に加入しているユーザが抽出され、パウダーアラートとして、スキー情報が送信される。
残りの 2 つの用途、「その場所にいるパウダーアラートユーザの取得」と「パウダーアラームの受信」はきわめてシンプルである。別のシーケンス図(図 5 (source)と 6(source))を示すことで、多少なりともイメージを明確にする。
図 5: スキー情報からパウダーアラームを取得する
図 6: パウダー場所に加入しているユーザーを取得する
コード化
ドメインのクラス
システムを始動するには、ドメインのクラスが必要になる。明白なドメインのクラスは USER と POWDERPLACE だけである。しかし、いくつかのヘルパークラスを使ってデータを移動させる必要もある。1 つはユーザからの加入メール用のクラス、もう 1 つはスキー情報アラームメッセージ用のクラスである。現時点では、info.powderalert.domain パッケージには実際のドメインクラスしか格納されていないが、ほかのクラスは infrastructure パッケージに残されている。詳細については、あとで説明する。
@Entity
@Table(name="user_table")
public class User implements Serializable {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="userId")
private Long id;
private String email;
private String firstName;
private String lastName;
@ManyToMany (fetch=FetchType.EAGER)
private ListpowderPlaces;
.. } @Entity
@Table(name="powderplace_table")
public class PowderPlace {
@Id @GeneratedValue(strategy= GenerationType.AUTO)
@Column( name="powderPlaceId")
private Long id;
private String name;
private Listusers;
.. }
サービス
シーケンス図を分析した結果、4 つのサービスが確認された。
MailService
mailserver に対するE メールの送受信を行ない、ほかのサービスが判読できる POJO に変換する。
public interface MailService {
void sendMail(User user, MailMessage message);
ListgetMail();
}
AdminService
システムに管理機能を付加し、User や PowderPlace の追加、削除、表示を行う。
public interface AdminService {
User addUser(User user);
User modifyUser(User user);
User getUser(Long id);
User getUser(String email);
boolean removeUser(User user);
List getUsers();
ListlistPowderPlaces();
void addPowderPlace(PowderPlace place);
PowderPlace getPowderPlace(Long id);
PowderPlace getPowderPlace(String name);
void removePowderPlace(PowderPlace place);
void modifyPowderPlace(PowderPlace place);
}
PowderAlertService
パウダーアラートを登録ユーザに届ける。
public interface PowderAlertService {
void powderAlert(PowderPlace place);
}
UserService
システムにおいて、アラート申し込みを処理する。
public interface UserService {
void subscribe(User user);
void unsubscribe(User user);
}
データアクセス
データを保存する必要があるが、残念ながらこれは常にやっかいな問題である。しかし、幸いなことに、Spring、Hibernate、Annotations を使うと、簡単にデータを保存できる。おそらく、すでにドメインのクラスにコメントを付けているだろう。現在、2 つの DA クラスがある。1 つはユーザを処理するクラスで、もう 1 つは powderplace を処理するクラスである。
public interface UserDAO {
void addUser(User user);
void updateUser(User user);
void removeUser(User user);
User getUser(Long id);
User getUser(String email);
ListgetUsers();
ListgetUsers(String location);
} public interface PowderPlaceDAO {
void addPowderPlace(PowderPlace place);
void updatePowderPlace(PowderPlace place);
void removePowderPlace(PowderPlace place);
PowderPlace getPowderPlace(Long id);
PowderPlace getPowderPlace(String name);
ListgetPowderPlaces();
}
インフラコンポーネント
Spring は、ワイヤリング、ルックアップ、Java Mail API へのアクセスの簡易化といった一部のインフラ関連事項で役に立っている。しかし、それでもうまく機能させるためには数多くのコードが必要である。たとえば、全体をブートストラッピングするサーブレットやメールサーバに対してポーリングを行なういくつかのタイマーが必要である。また、すでに述べたように、E メールを POJO に変換する際にはデータヘルパークラス、そしてユーザ名やパスワードなど、その他のデータを保存するためにいくつかのプロパティクラスが必要である。現時点では、これらのコンポーネントは除外しており、ダウンロードできるようにしてある(リソースのセクションを参照)。上述のすべてのインターフェイスの実装についても、同じことが言える。
さんご礁の最初の食べ物
PowderAlert #1 に問題点は一切ない。たとえば、きちんと系統立てられており、Spring を使ってワイヤリングを行ない、数多くの設計パターンを使っている。このように、Powder Alert #1 の階層化に注目してみると、ちゃんとしたアプリケーションになっている。しかし、ほかのシステムに対する統合の柔軟性、新しいサービスを進化させること、スケーリングについては、まるでさんご礁の初期段階のようである。
これは、ほかのシステムとのある種の統合を行なっている数多くのプロジェクトにおいて明らかになった非常に一般的な状況である。システム列をカバーする能力は優れているが、分散コンピューティングや統合のために必要とされるリソースは存在しないか無視されている。
要件の変化や進化する各種のサービスに対処できるアプリケーションを作成するには、このような課題に対応できる基盤の役割を果たすようなプラットフォームやツールが必要である。
もっと正確に言うと、ツールを寄せ集めたもの、むしろ LeathermanTM(サイト・英語)のようなものが好ましい。私たちのふたりのヒーローが、アフタースキーから何を学んだのか見てみよう。
アフタースキーでロスと会う
皆さんに誇りを持って紹介するのは Mule である。
私たちは、LeathermaTM ツールの IT 版を探していたのだが、ついに手に入れることができた。Mule プロジェクトで具体化された OpenSource Enterprise Service Bus を手に入れることができた。
Mule は、ESB アーキテクチャの概念を基盤とした電子通信プラットフォームである。簡単に言うと、貴社の既存のテクノロジーインフラ(Jms、Web サービス、E メールなど)を利用して複合的なサービスアプリケーションを構築する軽量の電子通信フレームワークである。
Mule の設計の重要な特徴は、最大限の柔軟性と拡張性である。統合に対応した Spring フレームワークであると考えることができる。
Mule のフレームワークは、きわめてスケーラブルな環境を実現することができるため、自社のビジネスコンポーネントを運用することができる。同じ VM 内に存在していようが、インターネットを介在していようが、使用している基盤移送に関係なく、コンポーネント間のすべてのやり取りをトランスペアレントに管理できる。侵入的ではないため、コンテナでどのようなオブジェクトでも管理でき、クラスを拡張したりインターフェイスを実装したりする必要は一切ない。貴社のサービスやロジックが汚染されることはなく、フレームのロックインを被ることもない。つまり、開発作業中のテストや規模の縮小にかなり適しているというである。
これは、環境透過性と呼ばれるものであり、Mule の主な特徴の 1 つである。これによって、ふたりはラップトップ上で山に登る途中でアプリケーション全体を開発することができ、最終的にオンライン状態になったときに、単純に新たに開発したコードをサーバに落とし、運用構成を変更し、必要に応じて分散環境で実行する。
フレームワークのコアとなるその他の機能は、JBI 統合、WebService 統合(Axis、Glue、または XFire を使用)、Spring フレームワークの統合、SEDA を基盤とした処理モデル、REST のサポート、XA サポートなどの宣言・プログラム処理サポート、ルーティングのエンドツーエンドサポート、イベントの変換である。
Mule(サイト・英語)のサイトで、機能の全リストと優れた導入資料を入手できる。
Mule の活用
私たちは強力なツールを手に入れたが、現在必要なものは、作業に最適なツールを示してくれるユーザマニュアルのようなものである。私たちは文字どおり大きなハンマーを使って釘を打ち込んでいるのではないことを理解する必要がある。
コンピュータサイエンスのほかの規律と同様に、誰かが同じ課題に直面し、これらのベストプラクティスをパターンという形で収集したことは大して驚くべきことではないはずである。したがって、統合に関するこのような問題を解決してもらうために、私たちには、(息を殺して・・・)統合パターンがある。
Gregor Hohpe の書籍『Enterprise Integration Patterns(企業の統合パターン)』の内容と図 7(source) に示した Mule のアーキテクチャを比べると、説明されているパターンの多くを実際に認識することができる。この書籍は是非とも読んでいただきたい。本当にすばらしい本である。この本に関して、少し警告しておかなければならないことがある。就寝前に読む本としては適していない。眠気をさそう本ではないからだ。
もう 1 つ、非常に役に立つリソースとして、Gregor の企業の統合パターン(EIP)(サイト・英語)のサイトがある。このサイトには、本に記載されているすべてのパターンがリストされており、ブログや記事のようなその他の有益な情報も掲載されている。
図 7: アーキテクチャの概要
とにかく、Mule のアーキテクチャと企業の統合パターンの利用に話を戻す。アーキテクチャ概要図の両端にあるこれら 2 つの「アプリケーション」バブルの間に統合パターンを並べた。
まず、「チャネル」と呼ばれるものを手に入れた。このコンポーネントの主目的は、2 つのエンドポイント間でデータをやり取りすることであり、メッセージチャネル(サイト・英語)を具体化したものにおいて、Gregor のサイトで使用済みのパターンを見つけることができる。
側面から読める人の場合、次に来るパターンは、「メッセージ受信者」名に隠されている。メッセージ受信者を使って、アプリケーションのデータを読んだり受信したりする。Mule では、受信者は移送プロバイダーの単なる 1 つの要素であり、Mule は、jms、soap、http、tcp、xmpp、smtp、file など、数多くの移送を提供している。
メッセージ受信者の場合の適切な EIP は、メッセージエンドポイント(サイト・英語)である。メッセージエンドポイントの主目的は、アプリケーションを電子通信チャネルに接続することである。このように、メッセージエンドポイントパターンは、アプリケーションの電子通信システムをカプセル化し、特定のアプリケーションのインターフェイスに向けて、一般的な電子通信 API をカスタマイズする。このカプセル化を行なうことによって、電子通信の移送透過性を実現する。メッセージエンドポイントは、アプリケーション用に特別に開発され、アプリケーションに組み込まれた特別なチャネルアダプター(サイト・英語)である。
次は、「コネクター」について。メッセージ受信者は、これに結合され、Mule 流の歩き方と話し方で通信できるようになる。接続は、チャネル別の要求を一端で受け取り、UMOEvent で話すもう一端にある Mule のコンポーネントに接続する。
ここでも、側面から読める人には、「トランスフォーマー」ボックスがある。この場合の適切な EIP はメッセージトランスレーター(サイト・英語)である。メッセージトランスレーターの主目的は、さまざまなデータフォーマットを使うシステムが、電子通信を利用してお互いに通信できるようにすることである。メッセージペイロードの変換に関心があるのであれば、Gregor のサイトの「Introduction to Message Transformation(メッセージ変換入門)」(サイト・英語)を参照するとよい。この概要を読んで得た知識は、問題の分野に関するすばらしい手引きになる。
話を Mule に戻す。トランスフォーマーを使ってメッセージを変換したり、さまざまなタイプに対してペイロードを引き起こしたりする。Mule では、標準的なメッセージフォーマットを定めていない(ただし、Mule は標準的なビジネスプロセス定義メッセージタイプをサポートできる)。したがって、ボックスから提供された変換は、オブジェクトに対する JMS メッセージ、標準的な XML トランスフォーマー、標準的なプロトコルトランスフォーマーなどの「型変換」である。データの変換は、アプリケーションに対してきわめて従順であり、Mule はシンプルではあるが強力な変換フレームワークを実現している。
次は、「インバウンドルーター」について話す。ここでは、企業の統合パターンのもう 1 つの事例、つまりメッセージルーター(サイト・英語)の事例がある。メッセージルーターの主目的は、1 つのメッセージチャネル(サイト・英語)からのメッセージを消費して、一連の条件に応じてさまざまなメッセージチャネルにメッセージを再発行することである。
メッセージルーター、インバウンドルーターの具体的な実装に関しては、それを使ってコンポーネントが受信したイベントを制御したり操作したりできる。一般的には、インバウンドルーターを使って、受信するイベントをフィルタリングしたり、受信する一連のイベントを集計したり、受信時に並べ替えたりすることができる。
これで、多かれ少なかれ、すべてのシークレットハンドシェークを実行したので、Mule の中枢、つまり UMO コンポーネントに到達することができる。
UMO コンポーネントが適正な尊敬を得られるようにするために(私たちは、誰かの魂について話している)、独自の見出しを取得する。それは、こんな感じである。:
UMO コンポーネント
Mule のアーキテクチャの中心にあるのは、ソースの束縛を受けずにやり取りでき、データの移動や配信を行なえる単一の自立的なコンポーネントである。このようなコンポーネントは、UMO コンポーネントと呼ばれ、さまざまな方法でほかのコンポーネントと連携して機能するように配置できる。これらのコンポーネントは、さまざまなソースからのデータを受け付け、元のソースにデータを送り返すように設定できる。
図 8: UMO コンポーネント
上で指定した「UMO lmpl」は、実際にはオブジェクトである。このオブジェクトは、JavaBean、EJB、ほかのフレームワークのコンポーネントなど、何でもかまわない。これは、受信したイベントに実際に何らかの処理を行なうクライアントコードである。Mule はオブジェクトに対して制限を一切加えないが、Mule が直接設定した場合は、デフォルトのコントラクターが必要である(Spring や Pico を使って設定した場合は、管理するオブジェクトにルールは一切課されない)。
UMO コンポーネントが強力で柔軟性が高いことは相当明白である。実際に、活力、想像力、スピードに満ち溢れた子どものようなものである。仕事中は、17 世紀のベネチアグラスでいっぱいの店に子どもを押し込んでおく必要があることを想像してみよう。だれも子どもを監視していない。そして、少し神経質になっているとしよう。それで、UMO コンポーネントが子どもだとすると、幼稚園に入れるのがよいかもしれない。Mule のコンテナーは、UMO コンポーネントの幼稚園で、Mule マネージャとモデルが保母である。これについては、図 9 (source)に示す。Mule マネージャは、UMO コンポーネントがすべてそこにあり、兄弟のようにリソースを共有していることを確認し、コンポーネントどうしでけんかをしないようにする。
図 9: Mule Server コンポーネント
これらのふたりの保母の中で、Mule マネージャが主となる保母である。Mule マネージャは、幼稚園の経営、各部署の子どもの数、営業時間などを管理する。Mule の観点で言えば、Mule マネージャは、モデルやそれが再度管理するコンポーネントに代わってすべてのコアサービスの設定を管理する。本当にたくさんのことを管理しているのである。
Mule 幼稚園のもうひとりの保母のことも忘れてはならない。モデルである。モデルは、私たちの UMO 園児の面倒を日々見てくれている。子どもたちをなだめ、食事を与え、幼稚園を取り巻く悪い環境から子どもたちを守り、UMO 園児たちのひとりひとりが同等に遊べるようにしてくれている。
モデルは、3 つのコントロールメカニズムを使って、Mule が UMO 園児たちとやり取りする方法を決定する。1 つめのコントロールメカニズムは、エントリーポイントリゾルバーである。エントリーポイントリゾルバーを使って、消費に代わってイベントを受信したときに、UMO コンポーネントでどのメソッドを呼び出すかを決定する。
Mule Model で使われている 2 つめのコントロールメカニズムはライフサイクルアダプターである。このメカニズムには、Mule コンポーネントのライフサイクルを基盤コンポーネントにマッピングする役割がある。
最後のコントロールメカニズムとしては、コンポーネントプールファクトリーがある。このメカニズムの役割は、任意の UMO コンポーネントに対して、適切なコンポーネントプールを作成することである。このようにして、私たちの UMO 園児の部門は・・・。
それでは、私たちのものぐさなふたりのヒーローに話を戻そう。彼らは、PowderAlert アプリケーションに、どのような方法で、そしてどこで Mule を適用すべきなのだろうか。
Mule への移行
図 10: Mule 化した PowderAlert Ver. 1
上の図 10(source) は、PowderAlert の最初のバージョンに Mule のコスチュームを着せると、どのような感じになるのかを簡単に図示したものである。このバージョンでは、シンプルな通信戦略として、Mule に VM オプションを使用している。メッセージはまだ関与していない。このシリーズの後の記事で、電子通信についても扱う。
それで、Mule を PowderAlert に活用する方法を説明するには、アプリケーションのアーキテクチャとそれを構成するコンポーネントをじっくり見てみる必要がある。
まず、自分のアプリケーションが提供・消費するサービス、そしてサービスを内部または外部に分類できるかどうかを判断する必要がある。この練習を行なう基本原理は、Mule に統合する方法において、特定のサービスを利用できるオプションを判断することである。
この状況で、サービスを分類することによって、自分のアーキテクチャにおいてサービスをどの程度変更することができるかを判断できる。スケールの一端に、自分自身で開発した内部サービスがあり、ほかのサービスに影響を与えることなくこのサービスを変更できる。これと正反対なものは、そのまま受け入れなければならない、変更される可能性がまったくないインターフェイスを付与する外部サービスである。
この定義を Mule に適用すると、任意のサービスを Mule に統合する方法に関する統合オプションの数は、外部サービスよりも内部サービスのほうが多いことを一般的なことばで説明できる。このように、内部サービスは Mule と強力に統合され、適切なアプリケーションフォームに記入すれば、Mule 幼稚園の園児になる可能性がある。
それでは、少し話しを戻し、もう一度上の図 1(source) を見てみよう。一般的には、PowderAlert アプリケーションを以下の 3 つの木目の粗いサービスに分けることができる。
- メールサーバ
- スキー情報サイト
- PowderAlert のコアサービス
メールサーバとスキー情報サイトにはまったく影響を与えない。これらの話し方や歩き方は固定されている。このように、これらは外部サービスに分類できる。したがって、Mule との非常に強力な統合によって、私たちが望んでいることは実現しないだろう。私たちは、サービスのインターフェイスに接続でき、ペイロードをコンポーネントに固有の要素から UMO 情報オブジェクトに変換できるものが必要なのである。
上の図 7 (source)をよく見ると、エンドポイントコンポーネントは、mailserver と Skiinfo サイトを Mule に統合するものとして突出した候補である。図からわかるように、スキー情報サイトは、E メールを送信することで PowderAlert とやり取りを行なうため、1 つの移送だけで、PowderAlert ユーザとの通信およびスキー情報サイトとの通信の両方を処理することができる。この場合、技術的な統合ポイント(E メール)は 1 つであるが、ペイロードのセマンティックスはスキー情報と PowderAlert のメッセージでは異なる。これは、2 種類の E メールエンドポイントで処理し、各エンドポイントのトランスフォーマーが、UMOEvent オブジェクトに応じて所定の SMTP メッセージを変換する。
あとは、PowderAlert のコアサービスである(PowderAlertService と UserService)。これがアプリケーションにおける実際のビジネスロジックであり、スキー熱狂者たち自身が開発したものであるため、サービスを変更することができる。このように、PowderAlert は複数の内部サービスに分類でき、コンポーネントを UMO 園児にすることができることを確信できる。たとえば、鼻をふき、問題なく過ごし、Mule の歌を覚えるたりする。そして、私たちは、それを Mule 幼稚園に送り、保母たちに監督してもらうことができる。
これで、残っているのは以下の課題である。
- Mule エンドポイントの作成、mailserver とのインターフェイス
- PowderAlert のコアサービスの UMO コンポーネントへの変換
- トランスフォーマーを作成して、E メールメッセージを適切な UMOEvent オブジェクトに変換
エンドポイントの作成
作成というよりも、構成と言ったほうがしっくりくる。Mule には、このようなすばらしい出来合いのエンドポイントが備わっているため、マニュアルに頼って、そこから文章をコピーする。
私たちは PowderAlert 1.0 にすでに 2 つのメールアカウントを作成している。1 つは、任意のパウダープレイスのアラートに登録したいと思っているユーザ用のアカウントで、もう 1 つはスキー情報サイトから情報を受け取るためのアカウントである。簡単に言うと、commons-net ライブラリを使ってメールサーバに対してポーリングを行なうのが最初のバージョンであったが、そのためには多くのコードが必要であった。Mule の POP3 エンドポイントに入る。
しかし、このようなコードをすべて捨てて、以下の構成に置き換えることができるようになった。
E メールアカウントが 2 つあるので、このエンドポイント、つまり唯一の相違点が URL におけるユーザー名である場合は、2 つのインスタンスが必要である。
E メールの送信に関しては、Spring が提供する機能で事足りるが、多少のコードや設定が必要になる。これも、捨て去り、以下の記述に置き換える。:
エンドポイントについては、これで問題ない。それでは、最初のバージョンですでにコード化したサービスについて見てみよう。すでに述べたように、UMO タイトルに対しては、強力な候補が実行されている。
PowderAlert のコアサービスを幼稚園に送信する
最初のバージョンを見ると、アプリケーションで本当に機能しているサービスとして際立っているのは 2 つのサービスである。
- ユーザの登録を処理する UserService
- ユーザにアラートを送信する PowderAlertService
この 2 つのサービスは、私たちの UMO である。これらのサービスを実際の Mule の UMO に変換するのは、長いプロセスのように思える。慌ててはいけない! UMO とは何だったろうか。通常の JavaBean でもよかったはずだ。実装について考えてみよう。
PowderAlertService:
public class PowderAlertServiceImpl implements PowderAlertService {
...(getters/setters)...
public void powderAlert(PowderPlace place) {
Listusers = userDAO.getUsers(place.getName())
for (User u : users) {
MailMessage msg = new PowderAlertMessage();
msg.setBody("Powder alert! "+ place.getName()
+ "has " + place.getCurrentSnowDepth()
+ " of FRESH snow!!!");
mailService.sendMail(u, msg);
}
}
UserService:
public class UserServiceImpl implements UserService {
..(getters/setters)..
public void subscribe(User user) {
// lookup powderplace
String place = user.getPowderPlaces().get(0).getName();
PowderPlace pp = powderPlaceDAO.getPowderPlace(place);
//check if user exist, in that case update user
User u = userDAO.getUser(user.getEmail());
if (null != u) {
u.getPowderPlaces().add(pp);
userDAO.updateUser(u);
} else {
Listpps = new
ArrayList();
pps.add(pp);
user.setPowderPlaces(pps);
userDAO.addUser(user);
}
}
}
このサービスは、「完全な」 UMO であり、実際にそのまま使うことができる。やるべきことは、トランスフォーマーを設置して、E メールメッセージを、サービスが理解できるドメインオブジェクトに変換するだけである。まず、全体の構成を調べて、その仕組みを理解する。
<mule-configuration id="PowderAlert" version="1.0">
<transformers>
<transformer name="PowderAlarmToPowderAlert"
className="info.powderalert.mule.PowderAlarmToPowderAlert"
returnClass="info.powderalert.domain.PowderAlert"/>
<transformer name="SubscriptionMailToUser"
className="info.powderalert.mule.SubscriptionMailToUser"
returnClass="info.powderalert.domain.User"/>
</transformers>
<!-- The Mule model initialises and manages your UMO components -->
<model name="PowderUMO">
<mule-descriptor name="PowderAlertUMO"
implementation="info.powderalert.service.impl.PowderAlertServiceImpl">
<inbound-router>
<endpoint address="pop3://alert:password@powderalert.info"
transformers="SkiinfoAlertToPowderAlarm"/>
</inbound-router>
<outbound-router>
<router
className="org.mule.routing.outbound.OutboundPassThroughRouter">
<endpoint address="smtp://powderman:password@powderalert.info"
transformers="org.mule.providers.email.transformers.ObjectToMimeMessage"/>
</router>
</outbound-router>
</mule-descriptor>
<mule-descriptor name="UserUMO"
implementation="info.powderalert.service.impl.UserServiceImpl">
<inbound-router>
<endpoint address="pop3://subscribe:password@powderalert.info"
transformers="SubscriptionMessageToUser"/>
</inbound-router>
</mule-descriptor>
</model>
</mule-configuration>
以下に構成を図示する。この図は、Mule の配信とともに提供されている「Config grapher」で作成したものである。
図にはトランスフォーマーは示されていないが、XML の
- PowderAlarmToPowderAlert
- SubscriptionMailToUser
名称は説明がなくてもわかるようなものになっている。両方のトランスフォーマーが POP3 エンドポイントからメールを受信し、ドメインオブジェクトに変換し、定義した UMO の受信者にもう一度送信する。
SMTP のエンドポイントについては、提供されている ObjectToMimeMessage トランスフォーマーを使って、私たちのメッセージを変換するため、エンドポイントが送信することができる。
ラッピング
この記事では、ポイント間の統合を行なうと、最終的には内側が固くて丈夫なさんご礁のようなコンピュータができてしまう。予測不可能な副作用のリスクを抱えることなくさまざまな統合ポイントを変更することは、最終的には不可能になる。
このことを例証するために、私たちは PowderAlert というシンプルなアプリケーションを持ち出した。PowderAlert の最初のバージョンはかなりうまく設計されているが、それでも、この記事で示したように、アプリケーションのアーキテクチャには、新しい統合ポイントやスケーリングに関する将来に対応できるだけの柔軟性がなかった。
このような課題に向き合うために、ESB アーキテクチャの概念を基盤とした電子通信プラットフォームである Mule を取り上げる。簡単に言うと、Mule は軽量の電子通信フレームワークであり、最大の柔軟性と拡張性を備えた設計になっている。Mule は、統合に対応した Spring フレームワークであると考えることができる。
この記事で Mule を使ったのは、メインのアプリケーション PowderAlert にトランスペアレントなほかのシステムとの統合を行なうためである。こうすることで、PowderAlert アプリケーションに対する影響を最小限に抑えながら新しいシステムとの統合が可能になる。
次の記事では、Mule を使ってアプリケーションを拡大・縮小し、最新の降雪情報を知りたがっているスキー熱狂者の要求をより多く処理する方法について詳しく見てみる。また、SMS を中心としたほかの配信チャネルに対するサポート要求の結果としても、この方法について考える。
次の記事では、ESB のスープのような世界に対する快適なスパイスとして、Mule IDE も取り上げる。
コードの免責事項
おそらく気づいているだろうが、ここで説明したコードにはいくつかの穴がある。実際のコードではなく、概念に焦点を当ててみる。単なる参考目的である。すぐに、コードをダウンロードして分解することでできるようになるだろう。
リソース
- http://mule.codehaus.org
- http://www.enterpriseintegrationpatterns.com
- http://www.craiglarman.com/
- http://www.craiglarman.com/book_applying/applying.htm
- http://www.springframework.org
- http://www.skiinfo.no
- http://www.powderalert.info
著者について
Rune Schumann (rune.schumann@bouvet.no) は、Bouvet の上級設計担当者として、1999 年から大規模な分散 JAVA システムを担当してきた。数年間、電気通信業界および小売業界において、SOA システムの設計、開発、プロジェクト管理の業務に携わる。また、国際会議やノルウェイ JUG で、SOA に関する講演も行なう。
Kjetil H.Paulsen (khp@bouvet.no - kjetil@java.no) は現在、Bouvet で上級ソフトウェア設計担当者の役職にあり、1996 年からこの業務を担当してきた。金融分野を中心に、設計担当者、開発部門のリーダーとして、さまざまな大規模分散 JAVA システムに取り組む。JavaZoneコンファレンスの年 1 回開催を中心とした活動を行なう javaBin(ノルウェイ JUG)委員会のメンバーでもある。さまざまなオープンソースプロジェクトでも活躍。
スキー熱狂者たち
原文はこちらです:http://www.infoq.com/articles/Evolutionary-integration
(このArticleは2006年6月1日にリリースされました)